package com.cargohu.aishouyu.auth.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cargohu.aishouyu.auth.service.MobileLoginRedisService;
import com.cargohu.aishouyu.auth.service.MobileLoginService;
import com.cargohu.aishouyu.auth.util.TokenUtil;
import com.cargohu.aishouyu.auth.vo.LoginTokenVo;
import com.cargohu.aishouyu.auth.vo.MemberLoginRedisVo;
import com.cargohu.aishouyu.auth.vo.MemberLoginVo;
import com.cargohu.aishouyu.common.CacheConstants;
import com.cargohu.aishouyu.common.DataStatus;
import com.cargohu.aishouyu.common.SecurityConstants;
import com.cargohu.aishouyu.common.enums.LoginTypeEnum;
import com.cargohu.aishouyu.config.properties.WechatOpenProperties;
import com.cargohu.aishouyu.framework.exception.BusinessException;
import com.cargohu.aishouyu.member.entity.Member;
import com.cargohu.aishouyu.member.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author aaron.wang
 * @date 2022/7/12
 **/
@Slf4j
@Service
public class MobileLoginServiceImpl implements MobileLoginService {

    @Autowired
    private MobileLoginRedisService loginRedisService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private WechatOpenProperties wechatOpenProperties;


    @Override
    public LoginTokenVo login(String code) throws Exception {

        Map params = new HashMap();
        params.put("secret", wechatOpenProperties.getSecret());
        params.put("appid", wechatOpenProperties.getAppId());
        params.put("grant_type", "authorization_code");
        params.put("code", code);
        String result = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token", params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        log.info("=====获取微信授权结果====:{}", jsonObject);
        String openid = jsonObject.get("openid").toString();
        Member member = memberService.getOne(Wrappers.<Member>query().lambda().eq(Member::getWxOpenid, openid).eq(Member::getDelFlag, DataStatus.NORMAL));
        if (member == null) {
            member = new Member();
            member.setWxOpenid(openid);
            memberService.saveOrUpdate(member);

        }
        MemberLoginVo memberLoginVo = new MemberLoginVo();
        memberLoginVo.setMemberId(member.getMemberId());
        // 生成token
        String token = TokenUtil.generateToken();
        // 保存登录信息到redis中
        loginRedisService.setLoginRedisVo(token, memberLoginVo);
        // 返回token
        LoginTokenVo loginTokenVo = new LoginTokenVo();
        loginTokenVo.setToken(token);
        return loginTokenVo;
    }

    @Override
    public MemberLoginRedisVo getLoginUserInfo() throws Exception {
        String token = TokenUtil.getToken();
        if (StringUtils.isBlank(token)) {
            return null;
        }
        return loginRedisService.getLoginRedisVo(token);
    }

    @Override
    public void logout() throws Exception {
        // 获取token
        String token = TokenUtil.getToken();
        // 删除缓存
        loginRedisService.deleteLoginRedisVo(token);
    }

    @Override
    public LoginTokenVo login(String phone, String code) throws Exception {

        String verifyCode = redisTemplate.opsForValue().get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + phone);
        if (StrUtil.isEmpty(verifyCode)) {
            throw new BusinessException("验证码已过期");
        }
        if (!verifyCode.equals(code)){
            throw new BusinessException("验证码错误");
        }
        Member member = memberService.getOne(Wrappers.<Member>query().lambda().eq(Member::getPhone, phone).eq(Member::getDelFlag, DataStatus.NORMAL));
        if (member == null) {
            member = new Member();
            member.setPhone(phone);
            memberService.saveOrUpdate(member);

        }
        MemberLoginVo memberLoginVo = new MemberLoginVo();
        memberLoginVo.setMemberId(member.getMemberId());
        // 生成token
        String token = TokenUtil.generateToken();
        // 保存登录信息到redis中
        loginRedisService.setLoginRedisVo(token, memberLoginVo);
        // 返回token
        LoginTokenVo loginTokenVo = new LoginTokenVo();
        loginTokenVo.setToken(token);
        return loginTokenVo;
    }

    /**
     * 发送手机验证码
     *
     * @param mobile mobile
     * @return code
     */
    @Override
    public String sendSmsCode(String mobile) {
        Object codeObj = redisTemplate.opsForValue()
                .get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile);

        if (codeObj != null) {
            log.info("手机号验证码未过期:{}，{}", mobile, codeObj);
            throw new BusinessException("验证码未过期!");
        }

        // String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
        String code = StrUtil.sub(mobile, mobile.length() - 4, mobile.length());

        log.debug("手机号生成验证码成功:{},{}", mobile, code);
        redisTemplate.opsForValue().set(
                CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile, code,
                SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
        return code;
    }

}
